package com.lyeducation.security;

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by Lintuer on 2017/10/26. AOP记录用户请求信息
 */
@Aspect
@Order(1)
@Component
public class WebLogAspect {
    private Logger logger = LoggerFactory.getLogger(getClass());
    ThreadLocal<Long> startTime = new ThreadLocal();

    // 定义切入点--正则表达式
    @Pointcut("execution(public * com.lyeducation.controllers.*.*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 获取HttpServletRequest
        ServletRequestAttributes attributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 获取要记录的日志内容
        logger.info(getRequestMsgByJsonString(request, joinPoint));
    }

    private String getRequestMsgByJsonString(HttpServletRequest request, JoinPoint joinPoint) {
        // 基本信息
        // 设置日期格式
        Map<String, Object> requestMsgMap = new LinkedHashMap<>();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        requestMsgMap.put("requestTime", df.format(new Date()));
        requestMsgMap.put("requestURL", request.getRequestURL().toString());
        requestMsgMap.put("requestURI", request.getRequestURI());
        requestMsgMap.put("queryString", request.getQueryString());
        requestMsgMap.put("remoteAddr", request.getRemoteAddr());
        requestMsgMap.put("remoteHost", request.getRemoteHost());
        requestMsgMap.put("remotePort", request.getRemotePort());
        requestMsgMap.put("localAddr", request.getLocalAddr());
        requestMsgMap.put("localName", request.getLocalName());
        requestMsgMap.put("method", request.getMethod());
        requestMsgMap.put("headers", getHeadersInfo(request));
        requestMsgMap.put("parameters", request.getParameterMap());
        requestMsgMap.put(
                "classMethod",
                joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        requestMsgMap.put("args", Arrays.toString(joinPoint.getArgs()));
        return JSON.toJSONString(requestMsgMap);
    }
    //    private BasicDBObject getBasicDBObject(HttpServletRequest request, JoinPoint joinPoint) {
    //        // 基本信息
    //        BasicDBObject r = new BasicDBObject();
    //        //设置日期格式
    //        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //        r.append("requestTime", df.format(new Date()));
    //        r.append("requestURL", request.getRequestURL().toString());
    //        r.append("requestURI", request.getRequestURI());
    //        r.append("queryString", request.getQueryString());
    //        r.append("remoteAddr", request.getRemoteAddr());
    //        r.append("remoteHost", request.getRemoteHost());
    //        r.append("remotePort", request.getRemotePort());
    //        r.append("localAddr", request.getLocalAddr());
    //        r.append("localName", request.getLocalName());
    //        r.append("method", request.getMethod());
    //        r.append("headers", getHeadersInfo(request));
    //        r.append("parameters", request.getParameterMap());
    //        r.append("classMethod", joinPoint.getSignature().getDeclaringTypeName() + "." +
    // joinPoint.getSignature().getName());
    //        r.append("args", Arrays.toString(joinPoint.getArgs()));
    //        return r;
    //    }

    /**
     * 获取头信息
     *
     * @param request
     * @return
     */
    private Map<String, String> getHeadersInfo(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }

    @AfterReturning(returning = "response", pointcut = "webLog()")
    public void runAfterReturning(Object response) {
        logger.info("response : {}", JSON.toJSONString(response));
        //        logger.info("SPEND TIME : {}", (System.currentTimeMillis() - startTime.get()) + "ms");
    }
}
